<?php


class WakKitFolder extends WakFolder {

    /**
     * builds from kit id, not path
     * @param string $id kit id, not path !!!
     */
    public function __construct($id) {
        $this->_id=$id;
        try {
            $this->_path=Webappkit::getPathFromId($id);
            $this->_cfg=Webappkit::getCfgFromId($id);
        } catch (WakBadCfg $e) {
            // bad cfg
        } catch (WakException $e) {
            // bad kit
        }
    }

    public function __toString() {
        return 'kit folder '.$this->_id;
    }

    /**
     * get kit diagnostic
     * missing = folder not found
     * bad_cfg = missing or invalid wak.ini
     * bad_class = kti class is missing or invalid
     * missing_file = some loaded file missing
     * missing_kit = require missing kit(s)
     * missing_subkit = load missing subkit
     * bad_php = not compatible with current php version
     * ok = everything sweat
     * @return string
     */
    public function getStatus() {
        if (!$this->exists()) // folder doesn't exist
            return 'missing';
        if (!$this->_cfg) // wak.ini don't exist or is not valid
            return 'bad_cfg';
        if (!$this->_checkFiles())
            return 'missing_file';
        if (!$this->_checkDependencies())
            return 'missing_kit';
        // check subkits
        if (!$this->_checkPhp())
            return 'bad_php';
        return 'ok';
    }

    /**
     * is kit valid ?
     * = is well formed, has every listed files
     * @return bool
     */
    public function isValid() {
        return in_array($this->getStatus(),array('ok','missing_kit','bad_php'));
    }

    /**
     * is kit functional ?
     * status == ok
     * @return bool
     */
    public function isFunctional() {
        return $this->getStatus()=='ok';
    }

    /**
     * get kit id
     * @return string
     */
    public function getId() {
        return $this->_id;
    }

    /**
     * get kit name = last id segment
     * @return string
     */
    public function getName() {
        $parts=explode('.',$this->_id);
        return end($parts);
    }

    /**
     * get kit version
     * @return string
     */
    public function getVersion() {
        return isset($this->_cfg['kit']['version'])
            ?$this->_cfg['kit']['version']:'';
    }

    /**
     * get kit description
     * @return string
     */
    public function getDescription() {
        return isset($this->_cfg['kit']['desc'])
            ?$this->_cfg['kit']['desc']:'';
    }

    /**
     * get kit link if provided
     * @return string
     */
    public function getLink() {
        return isset($this->_cfg['kit']['link'])
            ?$this->_cfg['kit']['link']:'';
    }

    /**
     * get tools list
     * @return array name => class
     */
    public function listTools() {
        return isset($this->_cfg['tools'])
            ?$this->_cfg['tools']:array();
    }

    /**
     * get configuration in INI format
     * @return string
     */
    public function getIni() {
        $file=new WakIniFile($this->realPath().'/wak.ini');
        if (!$ini=$file->getContent()) {
            // return sample ini there
            return self::$_sample_cfg;
        }
        return $ini;
    }

    /**
     * set Configuration
     * @param string INI format
     * @return bool
     */
    public function setIni($ini) {
        $file=new WakIniFile($this->realPath().'/wak.ini');
        return $file->setContent($ini);
    }

    /**
     * get tool config in INI format
     * search for custom config, or return default
     * @param string $name tool's name
     * @return string
     */
    public function getToolIni($name) {
        if (!isset($this->_cfg['tools'][$name]))
            return false;
        $file_path=$this->realPath().'/'.$name.'.tool.ini';
        // if config file exist, return its content
        if (file_exists($file_path)) {
            $file=new WakIniFile($file_path);
            return $file->getContent();
        }
        $class=$this->_cfg['tools'][$name];
        $cfg=eval('return '.$class.'::$default_cfg;');
        return WakIniFile::arrayToIni($cfg);
        //$tool=new
        return 'default';
    }

    /**
     * saves tool config from INI format
     * @param string $name tool's name
     * @param string $ini
     * @return bool
     */
    public function setToolIni($name, $ini) {
        $file_path=$this->realPath().'/'.$name.'.tool.ini';
        $file=new WakIniFile($file_path);
        return $file->setContent($ini);
    }

    /**
     * list subkits
     * @return array n => name
     */
    public function listSubkits() {
        return Webappkit::listKits($this->_path);
    }

    /**
     * get subkits as WakKitFolder instances
     * @return array $name => WakKitFolder
     */
    public function getSubkits() {
        $list=$this->listSubkits();
        $kits=array();
        foreach ($list as $name) {
            $kits[$name]=new WakKitFolder($this->_id.'.'.$name);
        }
        return $kits;
    }

    /**
     * does kit include unit tests ?
     * @return bool
     */
    public function hasTests() {
        return isset($this->_cfg['tools']['tests']);
    }

    /**
     * get tests report
     * @return WakTestsReporter
     */
    public function getTestsReport() {
        if (!$this->hasTests()
        or !$kit=&Webappkit::getKit($this->_id))
            return false;
        return $kit->tests->run();
    }

    /**
     * get dependencies list
     * = load_kits
     * @return array id => WakKitFolder
     */
    public function getDependencies() {
        if (!isset($this->_cfg['load_kits']))
            return array();
        $list=$this->_cfg['load_kits'];
        $kits=array();
        foreach ($list as $id) {
            // echo "<p>$id</p>";
            $kits[]=new WakKitFolder($id);
        }
        return $kits;
    }

    /**
     * @var array kit config if available
     */
    protected $_cfg=array();

    protected static $_sample_cfg='[kit]
; kit-wide informations

desc = "a short description"
version = "version string"
class = "kit class, optional"';

    /**
     * check that listed files exist
     * @return bool
     */
    protected function _checkFiles() {
        foreach ($this->_cfg['load_files'] as $file) {
            if (!file_exists($this->_path.$this->_libRealFile($file)))
                return false;
        }
        foreach ($this->_cfg['load_classes'] as $file) {
            if (!file_exists($this->_path.$this->_libRealFile($file)))
                return false;
        }
        return true;
    }

    /**
     * get real file name for a library file
     * = replace ending * by current php version
     */
    protected function _libRealFile($file) {
        if (substr($file,-1,1)=='*')
            $file=substr($file,0,-1).substr(phpversion(),0,1);
        // echo "<p>$file</p>";
        return $file;
    }

    /**
     * check kit dependencies
     */
    protected function _checkDependencies() {
        foreach ($this->_cfg['load_kits'] as $id) {
            if (!Webappkit::checkKit($id))
                return false;
        }
        return true;
    }

    /**
     * check that kit is compatible with current php version
     */
    protected function _checkPhp() {
        if (!isset($this->_cfg['kit']['phpversion']))
            return true;
        return Webappkit::isVersionWithinRange(phpversion(),$this->_cfg['kit']['phpversion']);
    }
}
